package ua.edu.nuos.jeetraining2012.cms.entity;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;

/**
 * Course entity bean.
 * <p/>
 * Bean that store information about course.
 *
 * @author Victor N. Ganichev victor.ganichev@gmail.com
 * @version 1.0 Date: 02.05.13 Time: 13:56
 * @since 1.0
 */
@Entity
@Table(name = "courses")
public class CourseEntity {

    /**
     * Course Id.
     * <p/>
     * Course identifier, Primary key.
     */
    @Id
    @SequenceGenerator(
            name = "courses_id_seq",
            sequenceName = "courses_id_seq",
            allocationSize = 1
    )
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "courses_id_seq"
    )
    @Column(
            name = "id",
            nullable = false,
            insertable = true,
            updatable = false,
            length = 11,
            precision = 0,
            columnDefinition = "SERIAL"
    )
    @NotNull
    private long id;

    /**
     * Course title.
     * <p/>
     * The title of the course.
     */
    @Column(
            name = "title",
            nullable = false,
            insertable = true,
            updatable = true,
            length = 256
    )
    @Basic(optional = false)
    @NotNull
    @Size(max = 256)
    private String title;

    /**
     * Short course descriptions.
     * <p/>
     * Use this description to advertise your course among others.
     */
    @Column(
            name = "short_description",
            nullable = false,
            columnDefinition = "TEXT"
    )
    @Basic(optional = false)
    @Size(max = 1024)
    @NotNull
    private String shortDescription;

    /**
     * Course description.
     * <p/>
     * Course descriptions. Place here information about the course, about prerequisites, course length, certificates
     * of accomplishment and so on.
     */
    @Column(
            name = "description",
            nullable = false,
            columnDefinition = "TEXT"
    )
    @Basic(optional = false)
    @Size(max = 2048)
    @NotNull
    private String description;

    /**
     * Course start date.
     * <p/>
     * Date of the beginning of the courses.
     * If course date isn't known yet, it can be null.
     */
    @Column(
            name = "start_date",
            nullable = true,
            insertable = true,
            updatable = true
    )
    @Basic(optional = true)
    @Temporal(value = TemporalType.DATE)
    private Date startDate;

    /**
     * Course finish date.
     * <p/>
     * Date, when the game is over.
     * If course finish date isn't known yet, it can be null.
     */
    @Column(
            name = "finish_date",
            nullable = true,
            insertable = true,
            updatable = true
    )
    @Basic(optional = true)
    @Temporal(value = TemporalType.DATE)
    private Date finishDate;

    /**
     * Course syllabus.
     * <p/>
     * The link to the syllabus file or its page.
     */
    @Column(
            name = "syllabus",
            nullable = false,
            insertable = true,
            updatable = true
    )
    private String syllabusLink;

    @Column (name = "logo", nullable = true, length = 512)
    @Basic(optional = true)
    private String logoURL;

    /** Define SVN repository name */
    @Column (name = "repository_name")
    @Basic(optional = true)
    private String repoName;

    /** Define Google Calendar ID. */
    @Column (name = "calendar_id")
    @Basic(optional = true)
    private String calendarId;

    /**
     * Course instructors.
     * <p/>
     * List of course instructors.
     */

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(
            name = "instructors_to_courses",
            joinColumns = @JoinColumn(name = "course_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "instructor_id", referencedColumnName = "id")
    )
    private List<CourseInstructorEntity> instructors;

    /**
     * Course students.
     * <p/>
     * List of course students.
     */
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "courseId", orphanRemoval = true)
    private List<UsersToCourseEntity> users;

//    Default constructor
    public CourseEntity() {}

// Getters & Setters

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getShortDescription() {
        return shortDescription;
    }

    public void setShortDescription(String shortDescription) {
        this.shortDescription = shortDescription;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getFinishDate() {
        return finishDate;
    }

    public void setFinishDate(Date finishDate) {
        this.finishDate = finishDate;
    }

    public String getSyllabusLink() {
        return syllabusLink;
    }

    public void setSyllabusLink(String syllabusLink) {
        this.syllabusLink = syllabusLink;
    }

    public List<CourseInstructorEntity> getInstructors() {
        return instructors;
    }

    public void setInstructors(List<CourseInstructorEntity> instructors) {
        this.instructors = instructors;
    }

    public List<UsersToCourseEntity> getUsers() {
        return users;
    }

    public void setUsers(List<UsersToCourseEntity> users) {
        this.users = users;
    }

    public String getLogoURL() {
        return logoURL;
    }

    public void setLogoURL(String logoURL) {
        this.logoURL = logoURL;
    }

    public String getRepoName() {
        return repoName;
    }

    public void setRepoName(String repoName) {
        this.repoName = repoName;
    }

    public String getCalendarId() {
        return calendarId;
    }

    public void setCalendarId(String calendarId) {
        this.calendarId = calendarId;
    }

    // Overrides

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CourseEntity that = (CourseEntity) o;

        if (id != that.id) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return (int) (id ^ (id >>> 32));
    }

    @Override
    public String toString() {
        return "CourseEntity{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", shortDescription='" + shortDescription + '\'' +
                ", description='" + description + '\'' +
                ", startDate=" + startDate +
                ", finishDate=" + finishDate +
                ", syllabusLink='" + syllabusLink + '\'' +
                ", logoURL='" + logoURL + '\'' +
                ", instructors=" + instructors +
                ", users=" + users +
                '}';
    }
}
